package com.pine.app.module.security.oauth.plugin.impl.loginTGT;

import com.pine.app.module.security.core.common.AuthConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaoyuan
 * @create 2020/3/5 16:32
 **/
@Slf4j
public class RedisOauthTgtServiceImpl  implements OauthTgtService{

    private static final String  TGT_CACHE_NAME = AuthConstant.CACHE_NAMESPACE+"OAUTH:TGT:";
    private static final String  TGT_CACHE_LIST_NAME = AuthConstant.CACHE_NAMESPACE+"OAUTH:TGT:IDS:";
    private static final String  TGT_CACHE_LOGIN_NAME = AuthConstant.CACHE_NAMESPACE+"OAUTH:TGT:LOGIN:";

    private RedisTemplate redisTemplate;

    public RedisOauthTgtServiceImpl(RedisTemplate   redisTemplate){
        this.redisTemplate = redisTemplate;
    }
    @Override
    public String createTGT() {
        String tgt = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(TGT_CACHE_LIST_NAME+tgt,tgt, Duration.ofMillis(60*1000));
        return tgt;
    }

    @Override
    public boolean checkTGT(String id) {
        try{
           Object s =    redisTemplate.opsForValue().get(TGT_CACHE_LIST_NAME+id);
            if(s!=null){
                return true;
            }
        }catch (Exception e){
            log.error("检查票据错误", e);
            return false;
        }
        return false;
    }

    @Override
    public void save(OauthTgtDTO tgtDTO) {
        redisTemplate.opsForValue().set(TGT_CACHE_NAME+tgtDTO.getId(),tgtDTO, Duration.ofMillis(tgtDTO.getExpire()*1000));
        redisTemplate.opsForValue().increment(TGT_CACHE_LOGIN_NAME + tgtDTO.getLoginName(), 1);
        redisTemplate.expire(TGT_CACHE_LOGIN_NAME + tgtDTO.getLoginName(), tgtDTO.getExpire()*1000, TimeUnit.MILLISECONDS);
        redisTemplate.delete(TGT_CACHE_LIST_NAME+tgtDTO.getId());
    }

    @Override
    public void remove(String tgtId) {
       OauthTgtDTO dto =  this.getOauthTgtDTO(tgtId);
       if(dto!=null){
           redisTemplate.delete(TGT_CACHE_NAME+tgtId);
           redisTemplate.opsForValue().decrement(TGT_CACHE_LOGIN_NAME+dto.getLoginName());
       }
        redisTemplate.delete(TGT_CACHE_LIST_NAME+tgtId);
    }

    @Override
    public OauthTgtDTO getOauthTgtDTO(String tgtId) {
        Object o = redisTemplate.opsForValue().get(TGT_CACHE_NAME+tgtId);
        if(o==null){
            return null;
        }
        return (OauthTgtDTO) o;
    }

    @Override
    public int getLoginCount(String loginName) {
        try {
            return (int) (getKey(TGT_CACHE_LOGIN_NAME+loginName));
        } catch (Exception e) {
            log.error("获取登陆错误次数错误", e);
            return 0;
        }
    }


    private long getKey(final String key) {
        return (long) redisTemplate.execute((RedisCallback<Long>) connection -> {
            RedisSerializer<String> redisSerializer =  redisTemplate.getStringSerializer();
            RedisSerializer<String> keySerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
            byte[] rowkey = keySerializer.serialize(key);
            byte[] rowval = connection.get(rowkey);
            try {
                String val = redisSerializer.deserialize(rowval);
                return Long.parseLong(val);
            } catch (Exception e) {
                return 0L;
            }
        });
    }
}
